/* This software was developed at the National Institute of Standards and
 * Technology by employees of the Federal Government in the course of
 * their official duties. Pursuant to title 17 Section 105 of the United
 * States Code this software is not subject to copyright protection and
 * is in the public domain.
 * NIST assumes no responsibility whatsoever for its use by other parties,
 * and makes no guarantees, expressed or implied, about its quality,
 * reliability, or any other characteristic.
 * <BR>
 * We would appreciate acknowledgement if the software is used.
 * <BR>
 * NIST ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
 * DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
 * FROM THE USE OF THIS SOFTWARE.
 * </PRE></P>
 * @author  rouil
 */

#include "mac802_16timer.h"
#include "mac802_16.h"
#include "scheduling/wimaxscheduler.h"

/*
 * Starts a timer for the given duration
 * @param time The timer duration
 */
void
WimaxTimer::start (double time)
{
    Scheduler & s = Scheduler::instance ();
    assert (busy_ == 0);
    busy_ = 1;
    paused_ = 0;
    stime = s.clock ();
    rtime = time;
    assert (rtime >= 0.0);
    s.schedule (this, &intr, rtime);	//schedule the event
}

/*
 * Stop the timer
 */
void
WimaxTimer::stop (void)
{
    Scheduler & s = Scheduler::instance ();

    assert (busy_);

    if (paused_ == 0)
        s.cancel (&intr);		//cancel the event

    busy_ = 0;
    paused_ = 0;
    stime = 0.0;
    rtime = 0.0;
}

void
WimaxTimer::pause (void)
{
    Scheduler & s = Scheduler::instance ();

    assert (busy_ && !paused_);

    paused_ = 1;
    rtime -= s.clock () - stime;

    assert (rtime >= 0.0);

    s.cancel (&intr);
}


void
WimaxTimer::resume (void)
{
    Scheduler & s = Scheduler::instance ();

    assert (busy_ && paused_);

    paused_ = 0;
    stime = s.clock ();

    assert (rtime >= 0.0);
    s.schedule (this, &intr, rtime);
}



/*
 * Handling function for WimaxFrameTimer
 * @param e The event that occured
 */
void
WimaxRxTimer::handle (Event * e)
{
    busy_ = 0;
    paused_ = 0;
    stime = 0.0;
    rtime = 0.0;
    mac->receive (record_->p);
    mac->removePacket (record_);
    //mac->receive ();
}

/*
 * Handling function for WimaxFrameTimer
 * @param e The event that occured
 */
void
WimaxT1Timer::handle (Event * e)
{
    busy_ = 0;
    paused_ = 0;
    stime = 0.0;
    rtime = 0.0;

    mac->expire (WimaxT1TimerID);
}

/*
 * Handling function for WimaxFrameTimer
 * @param e The event that occured
 */
void
WimaxT2Timer::handle (Event * e)
{
    busy_ = 0;
    paused_ = 0;
    stime = 0.0;
    rtime = 0.0;

    mac->expire (WimaxT2TimerID);
}

/*
 * Handling function for WimaxT3Timer
 * @param e The event that occured
 */
void
WimaxT3Timer::handle (Event * e)
{
    busy_ = 0;
    paused_ = 0;
    stime = 0.0;
    rtime = 0.0;

    mac->expire (WimaxT3TimerID);
}

/*
 * Handling function for WimaxT6Timer
 * @param e The event that occured
 */
void
WimaxT6Timer::handle (Event * e)
{
    busy_ = 0;
    paused_ = 0;
    stime = 0.0;
    rtime = 0.0;

    mac->expire (WimaxT6TimerID);
}

/*
 * Handling function for WimaxT12Timer
 * @param e The event that occured
 */
void
WimaxT12Timer::handle (Event * e)
{
    busy_ = 0;
    paused_ = 0;
    stime = 0.0;
    rtime = 0.0;

    mac->expire (WimaxT12TimerID);
}

/*
 * Handling function for WimaxT17Timer
 * @param e The event that occured
 */
void
WimaxT17Timer::handle (Event * e)
{
    busy_ = 0;
    paused_ = 0;
    stime = 0.0;
    rtime = 0.0;

    /** The node did not send a registration: release and
     *  age out Basic and Primary CIDs
     */
    PeerNode *peer = mac->getPeerNode (peerIndex_);
    mac->debug ("At %f in Mac %d did not register on time...release CIDs\n",
                NOW, mac->addr (), peerIndex_);
    mac->removePeerNode (peer);
}


/*
 * Handling function for WimaxT21Timer
 * @param e The event that occured
 */
void
WimaxT21Timer::handle (Event * e)
{
    busy_ = 0;
    paused_ = 0;
    stime = 0.0;
    rtime = 0.0;

    mac->expire (WimaxT21TimerID);
}

/*
 * Handling function for WimaxFrameTimer
 * @param e The event that occured
 */
void
WimaxLostDLMAPTimer::handle (Event * e)
{
    busy_ = 0;
    paused_ = 0;
    stime = 0.0;
    rtime = 0.0;

    mac->expire (WimaxLostDLMAPTimerID);
}

/*
 * Handling function for WimaxFrameTimer
 * @param e The event that occured
 */
void
WimaxLostULMAPTimer::handle (Event * e)
{
    busy_ = 0;
    paused_ = 0;
    stime = 0.0;
    rtime = 0.0;

    mac->expire (WimaxLostULMAPTimerID);
}

/*
 * Handling function for WimaxDCDTimer
 * @param e The event that occured
 */
void
WimaxDCDTimer::handle (Event * e)
{
    busy_ = 0;
    paused_ = 0;
    stime = 0.0;
    rtime = 0.0;

    mac->expire (WimaxDCDTimerID);
}

/*
 * Handling function for WimaxUCDTimer
 * @param e The event that occured
 */
void
WimaxUCDTimer::handle (Event * e)
{
    busy_ = 0;
    paused_ = 0;
    stime = 0.0;
    rtime = 0.0;

    mac->expire (WimaxUCDTimerID);
}

/*
 * Handling function for WimaxScanIntervalTimer
 * @param e The event that occured
 */
void
WimaxScanIntervalTimer::handle (Event * e)
{
    busy_ = 0;
    paused_ = 0;
    stime = 0.0;
    rtime = 0.0;

    mac->expire (WimaxScanIntervalTimerID);
}

/*
 * Handling function for WimaxT44Timer
 * @param e The event that occured
 */
void
WimaxT44Timer::handle (Event * e)
{
    busy_ = 0;
    paused_ = 0;
    stime = 0.0;
    rtime = 0.0;

    mac->expire (WimaxT44TimerID);
}

/*
 * Handling function for WimaxMobNbrAdvTimer
 * @param e The event that occured
 */
void
WimaxMobNbrAdvTimer::handle (Event * e)
{
    busy_ = 0;
    paused_ = 0;
    stime = 0.0;
    rtime = 0.0;

    mac->expire (WimaxMobNbrAdvTimerID);
}

/*
 * Handling function for WimaxRdvTimer
 * @param e The event that occured
 */
void
WimaxRdvTimer::handle (Event * e)
{
    busy_ = 0;
    paused_ = 0;
    stime = 0.0;
    rtime = 0.0;

    mac->expire (WimaxRdvTimerID);
    printf ("Rdv timeout going to channel %d\n", channel_);
    mac->setChannel (channel_);
}

/*
 * Indicates the beginning of DL subframe
 */
void
DlTimer::expire (Event * e)
{
    m_->start_dlsubframe ();
}

/*
 * Indicates the beginning of UL subframe
 */
void
UlTimer::expire (Event * e)
{
    m_->start_ulsubframe ();
}

/*
 * Initialize the MAC
 */
void
InitTimer::expire (Event * e)
{
    m_->init ();
}

/*
 * Handling function for ArqTimer
 * @param e The event that occured
 */
void
ARQTimer::expire (Event * e)
{
    connection_->getArqStatus ()->arqTimerHandler ();
}
